const net = require('net');
const LOCAL_PORT = 22;
const LOCAL_HOST = '192.168.3.60';
const REMOTE_PORT = 5555;
const REMOTE_HOST = 'localhost';
const ping = Buffer.concat([
  Buffer.alloc(4), Buffer.alloc(16), Buffer.from("3")
]);
function getPackageLength(buffer) {
  if (buffer.length < 21) {
    return 0;
  } else {
    return 21 + buffer.readInt32BE();
  }
}
function main() {
  let connections = {
    // hash:socket
  };
  let cache = null;
  let wsv = new net.Socket();
  let interval = 0;
  wsv.connect(REMOTE_PORT, REMOTE_HOST, () => {
    console.log("connected waiting server");
    interval = setInterval(() => {
      wsv.write(ping);
    });
  });
  wsv.on('data', buffer => {
    if (cache) {
      let buf = Buffer.concat([cache, buffer]);
      let packageLength;
      while (packageLength = getPackageLength(buf)) {
        let tmp = buf.slice(0, packageLength);
        buf = buf.slice(packageLength);
        let hash = tmp.slice(4, 20);
        let hashString = hash.toString('hex');
        let sign = tmp.slice(20, 21).toString();
        if (sign !== "3") {
          let body = tmp.slice(21);
          if (!connections[hashString]) {
            if (sign === "0") {
              let tcp = new net.Socket();
              tcp.connect(LOCAL_PORT, LOCAL_HOST, () => {
                connections[hashString].write(body);
              });
              tcp.on('data', buffer => {
                let head = Buffer.alloc(4);
                head.writeUInt32BE(buffer.length);
                let sign = Buffer.from('0');
                let data = Buffer.concat([head, hash, sign, buffer]);
                wsv.write(data);
              });
              tcp.on('close', () => {
                delete connections[hashString];
                let head = Buffer.alloc(4);
                head.writeUInt32BE(0);
                let sign = Buffer.from('1');
                let data = Buffer.concat([head, hash, sign]);
                wsv.write(data);
              });
              tcp.on('error', () => { });
              connections[hashString] = tcp;
            }
          } else {
            if (sign === "0") {
              connections[hashString].write(body);
            } else {
              connections[hashString].end();
              connections[hashString].destroy();
            }
          }
        }
      }
      cache = buf;
    } else {
      let buf = buffer.slice(0);
      let packageLength;
      while (packageLength = getPackageLength(buf)) {
        let tmp = buf.slice(0, packageLength);
        buf = buf.slice(packageLength);
        let hash = tmp.slice(4, 20);
        let hashString = hash.toString('hex');
        let sign = tmp.slice(20, 21).toString();
        if (sign !== 3) {
          let body = tmp.slice(21);
          if (!connections[hashString]) {
            if (sign === "0") {
              let tcp = new net.Socket();
              tcp.connect(LOCAL_PORT, LOCAL_HOST, () => {
                connections[hashString].write(body);
              });
              tcp.on('data', buffer => {
                let head = Buffer.alloc(4);
                head.writeUInt32BE(buffer.length);
                let sign = Buffer.from('0');
                let data = Buffer.concat([head, hash, sign, buffer]);
                wsv.write(data);
              });
              tcp.on('close', () => {
                delete connections[hashString];
                let head = Buffer.alloc(4);
                head.writeUInt32BE(0);
                let sign = Buffer.from('1');
                let data = Buffer.concat([head, hash, sign]);
                wsv.write(data);
              });
              tcp.on('error', () => { });
              connections[hashString] = tcp;
            }
          } else {
            if (sign === "0") {
              connections[hashString].write(body);
            } else {
              connections[hashString].end();
              connections[hashString].destroy();
            }
          }
        }
      }
      cache = buf;
    }
  });
  wsv.on('error', () => { });
  wsv.on('close', () => {
    console.log('disconnected from waiting server, auto retrying ...');
    clearInterval(interval);
    main();
  });
}
main();
